<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket客户端管理</title>
</head>
<body>
<div id="list">
    <fieldset>
        <legend>WebSocket客户端连接列表</legend>
        <p>
            <input type="button" name="Submit2" value="全选" onclick="sendActionMessage('selectAll')"/>
            <input type="button" name="Submit8" value="反选" onclick="sendActionMessage('inverse')"/>
            <input type="button" name="Submit3" value="不选" onclick="sendActionMessage('noSelect')"/>
            <input type="button" name="Submit7" value="断开选中WebSocket客户端连接" onclick="closeSelectedWebSocket()"/>
        </p>
        <table id="webSocketClientListTable">
            <tr>
                <th>序号</th>
                <th>选择</th>
                <th>客户端Id</th>
                <th>客户端名称</th>
                <th>会话ID</th>
                <th>连接时间</th>
            </tr>
        </table>
        <fieldset>
            <legend>
                给指定的WebSocket客户端发送消息
            </legend>
            <textarea id="textMessage" cols="70" rows="10">消息内容</textarea>
            <br/>
            <input type="button" id="btnSendMsg" value="发送消息" onclick="sendNoticeMessageToTargetClient()"/>
        </fieldset>
        <fieldset>
            <legend>
                控制台消息
            </legend>
            <fieldset>
                <legend>
                    要发送的消息
                </legend>
                <div id="needSendMessage"></div>
            </fieldset>
            <fieldset>
                <legend>
                    接收到的消息
                </legend>
                <div id="receiveMessage"></div>
            </fieldset>
        </fieldset>
        <fieldset>
            <legend>
                聊天消息
            </legend>
            <div id="chatMessage"></div>
        </fieldset>
    </fieldset>
</div>
</body>

<style type="text/css">
    tr, td, th {
        border: 1px solid #666666;
    }

    .curr{
        background-color: deeppink;
    }

    table {
        width: 100%;
        border-collapse: collapse; /* 边框合并属性  */
        text-align: center;
    }

</style>
<script type="text/javascript">
    var webSocketClientId;//与WebSocket服务器连接成功后,服务器端会返回一个clientId
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window  || 'MozWebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/websocket/webSocketClientList");
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function (event) {
        showReceiveMessage(event.data);
    };

    //连接成功建立的回调方法
    websocket.onopen = function (event) {
        showReceiveMessage(event.data);
    }

    /**
     * 根据接收到的操作消息执行相应的操作处理
     */
    function handleActionMessage(message,param){
        if(message=="selectAll"){
            selectall();
        }else if(message=="inverse"){
            inverse();
        }else if(message=="noSelect"){
            noselect();
        }else if(message=="closeWebSocket"){
            //需要关闭的WebSocket连接集合
            var webSocketClientArr=param.webSocketClientArr;
            if(webSocketClientArr.length==1 && webSocketClientArr[0].clientId==webSocketClientId){
                //关闭的是当前页面的webSocket客户端连接,不再往下执行
                return;
            }
            deleteTargetWebSocket(webSocketClientArr);
        }else if(message=="selectCheckBox"){
            var selectBoxValue = param.selectBoxValue;
            var checkedResult = param.checkedResult;
            selectCheckBox(selectBoxValue,checkedResult);
        }
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        //显示Websocket服务端推送回来的消息,测试代码
        showReceiveMessage(event.data);
        //解析接收到的消息，转成JSON对象
        var stringWebsocketMessage = JSON.parse(event.data);
        //根据消息类型进行数据处理
        var messageType = stringWebsocketMessage.messageType;
        if(messageType=="data"){
            //接收服务器端推送回来的数据,数据以Json对象数组的形式组装
            var jsonObjArr = stringWebsocketMessage.message;
            if (jsonObjArr.length > 0) {
                bindData(jsonObjArr);//将数据绑定到页面上显示
            }
        }else if(messageType=="action"){
            var messageData = stringWebsocketMessage.message;
            var messageText = messageData.messageText;
            var param = messageData.param;
            handleActionMessage(messageText,param);
        }else if(messageType=="text"){
            var messageData = stringWebsocketMessage.message;
            var user = messageData.user;
            var messageText = messageData.messageText;
            showChatMessage(user+":"+messageText);
        }else if(messageType=="notice"){
            var message = stringWebsocketMessage.message;
            showChatMessage(message);
        }else if(messageType=="sys"){//系统消息
            //记录服务器端返回的clientId
            webSocketClientId = stringWebsocketMessage.message.messageData.clientId;
        }
    }

    //连接关闭的回调方法
    websocket.onclose = function (event) {
        showReceiveMessage(webSocketClientId+"被WebSocket服务器端主动关闭连接了");
    }

    //监听窗口关闭事件，当窗口关闭时，主动去关闭websocket连接，防止连接还没断开就关闭窗口，server端会抛异常。
    window.onbeforeunload = function () {
        //关闭本页面的WebSocket链接
        closeCurrentWebSocket();
    }

    /**
     * 将接收到的消息显示在网页上的receiveMessage Div中
     */
    function showReceiveMessage(innerHTML) {
        document.getElementById('receiveMessage').innerHTML = innerHTML;
    }

    /**
     * 显示聊天消息
     */
    function showChatMessage(innerHTML){
        document.getElementById('chatMessage').innerHTML += innerHTML+"<br/>";
    }

    //关闭当前页面的WebSocket连接
    function closeCurrentWebSocket() {
        if(websocket != null){
            var paramObj={};
            //需要关闭连接的webSocketClient集合
            paramObj.webSocketClientArr=[];
            var webSocketClient = {};
            webSocketClient.clientId=webSocketClientId;
            paramObj.webSocketClientArr.push(webSocketClient);
            //发送动作消息通知服务器端关闭当前的WebSocket的连接
            sendActionMessage("closeWebSocket",paramObj);
            //连接关闭的回调方法
            websocket.onclose = function (event) {
                showReceiveMessage(webSocketClientId+"被WebSocket服务器端主动关闭连接了");
            }
            websocket=null;
        }else{
            showReceiveMessage("websocket还没有连接");
        }
    }

    //关闭选中的WebSocket连接
    function closeSelectedWebSocket() {
        if(websocket != null){
            //得到表格
            var table = document.getElementById("webSocketClientListTable");
            //得到表格中的checkbox元素数组
            var checkBoxArr = table.getElementsByTagName("input");
            var checkBoxArrLen = checkBoxArr.length;
            var paramObj={};
            //需要关闭连接的webSocketClient集合
            paramObj.webSocketClientArr=[];
            for (var i = 0; i <checkBoxArrLen; i++) {
                if (checkBoxArr[i].checked) {
                    //需要关闭的webSocket客户端
                    var webSocketClient = {};
                    //webSocket客户端的cliendId
                    webSocketClient.clientId=checkBoxArr[i].value;
                    paramObj.webSocketClientArr.push(webSocketClient);
                }
            }
            if(paramObj.webSocketClientArr.length!=0){
                //发送动作消息通知服务器端关闭WebSocket的连接
                sendActionMessage("closeWebSocket",paramObj);
            }else{
                alert("请至少选择一个要断开连接的WebSocket客户端");
            }
        }else{
            showReceiveMessage("websocket还没有连接");
        }
    }

    /**
     * 绑定数据到webSocketClientListTable
     * @param jsonObjArr
     */
    function bindData(jsonObjArr) {
        var table = document.getElementById("webSocketClientListTable");
        var rowsArr = table.rows;//表格的所有行
        var rowsLen = rowsArr.length ;//表格行数
        var lastRowIndex = rowsArr[rowsLen-1].rowIndex;//获取表格的最后一行的行索引
        for (var i = 0; i < jsonObjArr.length; i++) {
            var newRow = table.insertRow(-1);//插入新行
            newRow.rowIndex=(lastRowIndex+1+i);//新行的行索引
            var newCell_0 = newRow.insertCell(0);//在行中插入第一列
            newCell_0.innerHTML = newRow.rowIndex.toString();
            var newCell_1 = newRow.insertCell(1);//在行中插入第二列

            //创建input checkbox 元素
            var checkbox = document.createElement("input");
            checkbox.type = "checkbox";
            checkbox.name='checkbox'+newRow.rowIndex;
            checkbox.value = jsonObjArr[i].clientId;
            checkbox.index=newRow.rowIndex;
            checkbox.onclick=function(){
                var paramObj={};
                paramObj.selectBoxValue=this.value;//点击的checkBox对应的value
                paramObj.checkedResult = this.checked;
                sendActionMessage("selectCheckBox",paramObj);
            }
            //newCell_1添加checkbox
            newCell_1.appendChild(checkbox);
            //newCell_1.innerHTML = "<input type='checkbox' name='checkbox'+i value='" + jsonObjArr[i].clientId + "' />";
            var newCell_2 = newRow.insertCell(2);//在行中插入第三列
            newCell_2.innerHTML = jsonObjArr[i].clientId;
            var newCell_3 = newRow.insertCell(3);//在行中插入第四列
            newCell_3.innerHTML = jsonObjArr[i].clientName;
            var newCell_4 = newRow.insertCell(4);//在行中插入第五列
            newCell_4.innerHTML = jsonObjArr[i].sessionId;
            var newCell_5 = newRow.insertCell(5);//在行中插入第六列
            newCell_5.innerHTML = jsonObjArr[i].connTime;
            //如果是代表当前页面的webSocket客户端Id
            if(jsonObjArr[i].clientId==webSocketClientId){
                //设置行特殊样式
                newRow.className="curr";
                //设置不可用选中
                checkbox.disabled=true;
            }
        }
    }

    /**
     * 全选
     */
    function selectall() {
        var table = document.getElementById("webSocketClientListTable");
        var selectBox = table.getElementsByTagName("input");
        for (var i = 0; i < selectBox.length; i++) {
            if(selectBox[i].disabled==false){
                selectBox[i].checked = true;
            }
        }
    }

    /**
     * 发送通知消息到选中的客户端
     */
    function sendNoticeMessageToTargetClient(){
        var messageText = document.getElementById("textMessage").value;
        var table = document.getElementById("webSocketClientListTable");
        var selectBox = table.getElementsByTagName("input");
        var targetClientArr=[];//存放需要发送消息的目标客户端
        for (var i = 0; i < selectBox.length; i++) {
            if (selectBox[i].checked) {
                var targetClient ={};
                targetClient.clientId=selectBox[i].value;
                targetClientArr.push(targetClient);
            }
        }
        var paramObj={};
        paramObj.targetClientArr=targetClientArr;
        //需要发送的消息数据
        var messageData={};
        messageData.messageText=messageText;
        messageData.param = paramObj;
        //发送通知消息
        sendMessage(messageData,"notice");
    }

    /**
     *发送操作动作Message
     * action 执行的动作
     * param 参数
     */
    function sendActionMessage(messageText,param){
        //需要发送的消息数据
        var messageData={};
        messageData.messageText=messageText;
        if(param!=undefined){
            messageData.param = param;
        }
        //发送消息
        sendMessage(messageData,"action");
    }


    /**
     * 发送消息
     * @param messageData 消息数据
     * @param messageType 消息类型
     */
    function sendMessage(messageData,messageType) {
        if(websocket!=null){
            //构建需要发送的消息对象
            var stringWebsocketMessage={};
            stringWebsocketMessage.message=messageData;
            stringWebsocketMessage.messageType=messageType;//指明要发送的消息类型，WebSocket服务器端接收到消息后会根据消息类型进行数据推送
            //使用原生的JSON对象的stringify方法将stringWebsocketMessage转成JSON对象并使用WebSocket发送JSON对象
            var message = JSON.stringify(stringWebsocketMessage);
            showNeedSendMessage(message);//测试代码，将要发送的消息打印到页面上显示
            websocket.send(message);//发送消息
        }else{
            alert('请先连接WebSocket服务器')
        }

    }

    /**
     * 显示需要发送的消息
     */
    function showNeedSendMessage(innerHTML){
        document.getElementById('needSendMessage').innerHTML = innerHTML;
    }
    /**
     *全不选
     */
    function noselect() {
        var table = document.getElementById("webSocketClientListTable");
        var selectBox = table.getElementsByTagName("input");
        for (var i = 0; i < selectBox.length; i++) {
            selectBox[i].checked = false;
        }
    }

    /**
     * 反选
     */
    function inverse() {
        var table = document.getElementById("webSocketClientListTable");
        var selectBox = table.getElementsByTagName("input");
        for (var i = 0; i < selectBox.length; i++) {
            if (selectBox[i].checked) {
                selectBox[i].checked = false;
            } else {
                selectBox[i].checked = true;
            }
        }
    }

    /**
     * 删除已经断开的WebSocket客户端的行
     */
    function deleteTargetWebSocket(webSocketClientArr) {
        var table = document.getElementById("webSocketClientListTable");
        var checkBoxArr = table.getElementsByTagName("input");
        var webSocketClientArrLen=webSocketClientArr.length;
        var checkBoxLen = checkBoxArr.length;
        for (var i = 0; i < webSocketClientArrLen; i++) {
            for (var j = 0; j < checkBoxLen; j++) {
                var webSocketClient = webSocketClientArr[i];
                if (webSocketClient.clientId==checkBoxArr[j].value) {
                    //删除checkBox的索引对应的行
                    table.deleteRow(checkBoxArr[j].index);
                    break;
                }
            }
        }
        //由于删除了一些行,导致序号那一列的数字顺序乱了,因此在这里将序号列的值重新计算
        var rowsArr = table.rows;
        var rowsArrLen = rowsArr.length;
        var row_0 = rowsArr[0];
        row_0.rowIndex=0;
        for(var i=1;i<rowsArrLen;i++){
            var row = rowsArr[i];
            row.rowIndex=i;
            var cells = row.cells;
            cells[0].innerHTML=i;
        }
    }

    /**
     * 选择指定value值的CheckBox
     */
    function selectCheckBox(selectBoxValue,checkedResult){
        var table = document.getElementById("webSocketClientListTable");
        var checkBoxArr = table.getElementsByTagName("input");
        var checkBoxArrLen = checkBoxArr.length;
        for (var i = 0; i <checkBoxArrLen; i++) {
            if (checkBoxArr[i].value==selectBoxValue) {
                checkBoxArr[i].checked=checkedResult;
                break;
            }
        }
    }

    /**
     * 隐藏、显示Div
     * @param targetDiv 需要操作的DIV
     * @param display 1显示 0隐藏
     */
    function showOrHiddenDiv(targetDiv, display) {
        if (display == "1") {
            targetDiv.style.display = "";
        }
        else {
            targetDiv.style.display = "none";
        }
    }
</script>
</html>